<template>
  <div class="layout">
    <div class="msgBody">{{ msg }}</div>
    <input v-model="sendMsg.toId" style="width: 200px; height: 30px; margin-top: 20px" />
    <input v-model="sendMsg.msg" style="width: 200px; height: 30px; margin-top: 20px" />
    <button @click="websocketsend()" style="width: 100px; height: 30px">发送</button>
    <button @click="close" style="width: 100px; height: 30px">断开链接</button>
    <button @click="init" style="width: 100px; height: 30px">建立链接</button>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { useUserStore } from '@/stores'
const userStore = useUserStore()
const websocket = ref(null)
const lockReconnect = ref(false)
const timeout = ref(20 * 1000)
const timeoutObj = ref(null)
const serverTimeoutObj = ref(null)
const timeoutnum = ref(null)
const msg = ref('')
const sendMsg = ref({
  toId: '',
  msg: ''
})

onMounted(() => {
  initWebSocket()
})

onUnmounted(() => {
  websocket.value.close()
})

const initWebSocket = () => {
  const wsuri = 'ws://localhost:8989/websocket/' + userStore.userInfo.id
  //建立连接
  websocket.value = new WebSocket(wsuri)
  //连接成功
  websocket.value.onopen = () => websocketonopen()
  //连接错误
  websocket.value.onerror = (e) => websocketonerror(e)
  //接收信息
  websocket.value.onmessage = (event) => websocketonmessage(event)
  //连接关闭
  websocket.value.onclose = () => websocketclose()
}

const reconnect = () => {
  //重新连接
  //判断链接状态，true就是链接，false是断开，这里如果是链接状态就不继续执行了，跳出来。
  if (lockReconnect.value) {
    return
  }
  //把链接状态改为true
  lockReconnect.value = true
  //没连接上会一直重连，设置延迟避免请求过多
  timeoutnum.value && clearTimeout(timeoutnum.value)
  timeoutnum.value = setTimeout(function () {
    //初始化新连接
    initWebSocket()
    //把链接状态改为false
    lockReconnect.value = false
  }, 5000)
}

const reset = () => {
  //清除时间
  clearTimeout(timeoutObj.value)
  clearTimeout(serverTimeoutObj.value)
  //重启心跳
  start()
}
const start = () => {
  //开启心跳
  //有延迟时间的就清除掉
  timeoutObj.value && clearTimeout(timeoutObj.value)
  serverTimeoutObj.value && clearTimeout(serverTimeoutObj.value)
  //从新创建计时器
  timeoutObj.value = setTimeout(function () {
    console.log(11111111)
    //这里发送一个心跳，后端收到后，返回一个心跳消息
    if (websocket.value.readyState == 1) {
      //如果连接正常发送信息到后台
      websocketsend({ toId: userStore.userInfo.id, msg: 'ping' })
    } else {
      //否则重连
      reconnect()
    }
    serverTimeoutObj.value = setTimeout(function () {
      //超时关闭
      websocket.value.close()
    }, timeout.value)
  }, timeout.value)
}
//链接成功时执行的方法
const websocketonopen = () => {
  //连接成功事件
  websocketsend({ toId: userStore.userInfo.id, msg: 'heartbeat' })
  //提示成功
  console.log('连接成功', websocket.value)
  //开启心跳
  start()
}
//连接失败事件
const websocketonerror = (e) => {
  //错误
  console.log('WebSocket连接发生错误')
  //重连
  reconnect()
}
//连接关闭事件
const websocketclose = (e) => {
  websocket.value.close()
  //提示关闭
  console.log('连接已关闭')
  //重连
  reconnect()
}
//接收服务器推送的信息
const websocketonmessage = (event) => {
  //打印收到服务器的内容
  console.log('收到服务器信息', event.data)
  let messageObj = JSON.parse(event.data)
  if(messageObj.toId != userStore.userInfo.id) {
    msg.value = event.data
  }
  //收到服务器信息，心跳重置
  reset()
}
const websocketsend = (msg) => {
  if (!msg) msg = sendMsg.value
  console.log(JSON.stringify(msg))
  //向服务器发送信息
  websocket.value.send(JSON.stringify(msg))
}
</script>

<style scoped lang="scss">
.layout {
  position: relative;
  width: 100%;
  height: 100%;
}
.msgBody {
  width: 500px;
  height: 300px;
  border: 1px solid rgb(95, 79, 79);
}
</style>